from flask import Flask, render_template, jsonify
from bs4 import BeautifulSoup
import urllib.request
from time import sleep
from pyecharts.charts import Bar, Pie
from pyecharts import options as opts
import webbrowser
import threading
import json
import os
import re  # 新增正则表达式模块用于价格解析

app = Flask(__name__)
DATA_FILE = 'huinong_data.json'  # 数据存储文件

# 柠檬主题颜色配置（橙色和黄色为主）
AGRI_COLORS = ["#F57C00", "#FFF176", "#1976D2", "#455A64"]


def save_to_json(data):
    """保存数据到JSON文件"""
    with open(DATA_FILE, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


def load_from_json():
    """从JSON文件加载数据"""
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    return []


def get_huinong_data(page=1):
    """获取惠农网柠檬数据（优化标签定位和价格解析）"""
    url = f'https://www.cnhnb.com/p/ningmeng-{page}/'  # 修改为柠檬商品页
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
    }
    req = urllib.request.Request(url, headers=headers)
    sleep(1)  # 遵守网站爬取规则

    try:
        with urllib.request.urlopen(req) as html:
            soup = BeautifulSoup(html.read(), 'html.parser')
            products = soup.find_all('div', class_='show-ctn')  # 正确的商品容器类名

            data = []
            for product in products:
                # 提取商品名称（实际标签可能为h3或div，需根据页面调整）
                name_elem = product.find('h3', class_='shops-name') or product.find('div', class_='shops-text')
                product_name = name_elem.get_text(strip=True) if name_elem else '未知产品'

                # 提取供应商（标签可能为shop-btm中的a标签）
                supplier_elem = product.find('a', class_='shop-name')
                supplier = supplier_elem.get_text(strip=True) if supplier_elem else '未知供应商'

                # 提取价格（处理不同单位：斤、吨、箱等）
                price_elem = product.find('div', class_='shops-price')
                price_text = price_elem.get_text(strip=True) if price_elem else '0.00元/斤'
                price_value, price_unit = parse_price(price_text)  # 使用价格解析函数
                item_price = f"{price_value:.2f}元/{price_unit}"

                # 提取产地（可能与供应商信息在同一标签）
                addr_elem = product.find('div', class_='shop-btm')
                address = addr_elem.get_text(strip=True).split('\n')[0] if addr_elem else '未知地区'

                # 提取销量（通过正则表达式从文本中匹配）
                sales_elem = product.find('div', class_='shops-text')
                sales_text = sales_elem.get_text(strip=True) if sales_elem else ''
                sales_match = re.search(r'成交(\d+\.?\d*)万元', sales_text)
                sales = sales_match.group(1) if sales_match else '0'

                data.append({
                    'name': product_name,
                    'supplier': supplier,
                    'price': item_price,
                    'address': address,
                    'sales': sales,
                    'unit': price_unit  # 保存单位用于后续分析
                })
            return data
    except Exception as e:
        print(f"柠檬数据爬取失败: {str(e)}")
        return []


def parse_price(price_text):
    """解析价格文本，提取数值和单位"""
    if not price_text:
        return 0.0, '斤'

    # 正则表达式匹配数值和单位
    pattern = r'(\d+\.?\d*)(.*)'
    match = re.match(pattern, price_text)
    if not match:
        return 0.0, '斤'

    value = float(match.group(1)) if match.group(1) else 0.0
    unit = match.group(2) or '斤'  # 处理单位为空的情况

    # 标准化单位（可根据实际情况扩展）
    if '吨' in unit:
        unit = '吨'
    elif '箱' in unit or '件' in unit:
        unit = '箱'
    elif 'kg' in unit.lower() or '公斤' in unit:
        unit = 'kg'
    else:
        unit = '斤'  # 默认单位

    return value, unit


def create_price_chart(products):
    """创建价格对比柱状图（优化数据过滤）"""
    valid_products = [p for p in products if p['price'] != '0.00元/斤']  # 过滤无效价格

    c = (
        Bar(init_opts=opts.InitOpts(width='100%', height='350px', bg_color='white'))
        .add_xaxis([p['name'][:15] for p in valid_products])  # 截断过长名称
        .add_yaxis('价格(元/斤)', [float(p['price'].split('元/')[0]) for p in valid_products],
                   itemstyle_opts=opts.ItemStyleOpts(color=AGRI_COLORS[0]))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="柠檬价格对比", subtitle="数据来源：惠农网", pos_left='center'),
            xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
            yaxis_opts=opts.AxisOpts(
                name="价格(元/斤)",
                splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts(color='#eee'))
            )
        )
    )
    return c.dump_options_with_quotes()


def create_region_chart(products):
    """创建地区分布饼图（优化地区提取）"""
    region_data = {}
    for p in products:
        # 提取省份（假设地址格式为“XX省XX市”或“XX市”）
        address = p['address']
        if '省' in address:
            region = address.split('省')[0]
        elif '市' in address:
            region = address.split('市')[0]
        else:
            region = '其他'
        region_data[region] = region_data.get(region, 0) + 1

    c = (
        Pie(init_opts=opts.InitOpts(width='100%', height='350px', bg_color='white'))
        .add('', list(region_data.items()), radius=['40%', '70%'], itemstyle_opts=opts.ItemStyleOpts(color=AGRI_COLORS))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="柠檬产地分布", subtitle="数据来源：惠农网", pos_left='center'),
            legend_opts=opts.LegendOpts(pos_right='10%', orient='vertical')
        )
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}家 ({d}%)"))
    )
    return c.dump_options_with_quotes()


@app.route('/')
def index():
    # 爬取并保存数据
    page_data = get_huinong_data(page=1)
    save_to_json(page_data)  # 保存到JSON文件

    # 加载数据（确保数据有效）
    products = load_from_json() or []
    products = products[:12]  # 取前12条数据展示

    # 生成图表（处理空数据情况）
    price_chart = create_price_chart(products) if products else ""
    region_chart = create_region_chart(products) if products else ""

    return render_template(
        'index.html',
        products=products,
        price_chart=price_chart,
        region_chart=region_chart,
        page_title="惠农柠檬市场分析"
    )


@app.route('/api/data')
def get_data():
    """提供JSON数据接口"""
    return jsonify(load_from_json())


def open_browser():
    """自动打开浏览器"""
    sleep(2)
    webbrowser.open_new('http://127.0.0.1:5000')


if __name__ == '__main__':
    if not os.path.exists('templates'):
        os.makedirs('templates')
    if not os.path.exists('static'):
        os.makedirs('static')

    threading.Thread(target=open_browser).start()
    app.run(debug=True, port=5000)